import hashlib
from flask import Flask, jsonify, request, render_template
from uuid import uuid4
import requests
import json
import modules.transaction
import modules.net.pynet
import modules.net.htmlglobalvalue
import modules.consensus 
import modules.block 
import modules.appconfig
import modules.db
import dto.block
import dto.utx
import dto.transaction
import dto.tipblkInfo
import dao.blockStore
import util.ctime 
import util.chash 
import modules.db
import dto.rollback
import copy
import modules.log
from  util.singelMode import singleton
 
@singleton
class CBlockchain:
    def __init__(self):
        self.isolatedBockCachedPool  = []
        self.__attachApi()
        self.__lastblk=None
        self.__copyrightmanageraccount='d0b5e326efb065ef8830d71430cf655f4c541762'
        self.isolatedBlocks=[]
        self.fivePreBlockhashDequeFromTheTipBlk = []
        self.fiveNewBlockDequeFromTheTipBlk = []
        self.genesisBlockHash = ""
        self.isFirstedLoad=False
    def __call__(self):
        return self
    def init(self):
        if(self.loadLocalchain()):
            modules.log.Clog.logger.info("完成本地区块加载")
            modules.log.Clog.logger.info("和远端节点区块同步中。。。。。。。。。。。。。。")
            self.syncChainWithOtherNode()
            modules.log.Clog.logger.info("和远端节点区块完成。。。。。。。。。。。。。。")
        return False
    def getGenesisBlockHash(self):
        if self.genesisBlockHash == "":
            genesisBlockInfo = modules.db.CDb.getValueByKey("chainIndexFile",f'blksetByHeight{0}')
            if genesisBlockInfo !=None:
                self.genesisBlockHash = genesisBlockInfo.split(",")[0].split(":")[0]
                return self.genesisBlockHash
            else:
                self.init()
        else:
            return self.genesisBlockHash
    def ifIsThecopyrightmanageraccount(self,address):
        if address==self.copyrightmanageraccount:
            return True
        else:
            return False
 
    def loadLocalchain(self):
        
        tipblkInfoStr = modules.db.CDb.getValueByKey("chainIndexFile","tipBlock")
        if tipblkInfoStr !=None:
            tipblkIndo = dto.tipblkInfo.CTipblkInfo.deserializeFromJsonStr(tipblkInfoStr)
            storefilename = tipblkIndo.storeFile
            lastblk = modules.block.CBlock.getBlockFromDiskByFileName(storefilename)
            if(modules.block.CBlock.validBlock(lastblk.serializeToPyObject())):
            # if lastblk.valid():
                self.__lastblk  = lastblk.serializeToPyObject()
                self.fivePreBlockhashDequeFromTheTipBlk = self.indexBlockHashfromCurrentBLock(lastblk.selfhash,lastblk.height,5)
                return True
            else:
                modules.log.Clog.logger.info("本地区块加载失败")
                return False
        else:
            modules.db.CDb.setValue("chainIndexFile","blckNumber",str(-1))
            self.saveGenesisBlock()
            modules.log.Clog.logger.info("第一次使用,创建创世区块")
            self.isFirstedLoad = True
        return True

    def saveGenesisBlock(self):
        genesisBlock=dto.block.CBlock.deserializeFromJsonfile(modules.appconfig.CAppconfig.configFromFile['genesisBlockConfigFile'])
        modules.block.CBlock.processBlock(genesisBlock,0)
        
    @property
    def last_block(self):
        #Returns the last Block in the chain
        return self.__lastblk
    @property
    def copyrightmanageraccount(self):
        return self.__copyrightmanageraccount
    @last_block.setter
    def last_block(self,value):
        self.__lastblk = value

    
    
    
    def findcopyrightcotent(self,copyrightID):
        t=len(self.fiveNewBlockDequeFromTheTipBlk)
        i=0
        j=-1
        while i<t:
            for tx in self.fiveNewBlockDequeFromTheTipBlk[j]['transactions']:
                for txout in tx['txouts']:
                    if txout['value']==copyrightID:
                        return i,txout['content']
            i=i+1
            t=t-1
        return -1,""
    def updateUTXOset(self,blockhash):
        """
        block 是自定义类型
        """
               
            
        path = modules.appconfig.CAppconfig.configFromFile['chainFilePath']
        blkStoreInfo = modules.db.CDb.getValueByKey("chainIndexFile",blockhash)
        if blkStoreInfo != None:
            storefilename=f'{blockhash}.dat'
            path=modules.appconfig.CAppconfig.configFromFile['chainFilePath']+blockhash[0:2]
            filename=f'{path}/{storefilename}'

            block = dto.block.CBlock.deserializeFromJsonfile(filename)
            # block = modules.block.CBlock.getBlockFromDiskByhash(blockhash)
            revblock = dto.rollback.CRevblock()
            revblock.blkhash = block.selfhash
            # for tx in block.transactions:
            for index, tx in enumerate(block.transactions):
                #update txinfo in chainIndexdata
                key = tx['selfhash']
                timestamp=tx['timestamp']
                value = f'{storefilename},{block.selfhash},{index},{block.height},{timestamp}'
                modules.db.CDb.setValue("chainIndexFile",key,value) 
                   
                tx = dto.transaction.CTransaction.deserializeFromPyObject(tx)
                if tx.isAddCopyRightToTheChainTx() == False:
                    revtx= dto.rollback.CRevTx()
                    revtx.blkhash = block.selfhash 
                    revtx.txhash = tx.selfhash
                    for vin in tx.txins:
                        updatedOuts = []
                        unSpendOutStr = modules.db.CDb.getValueByKey("chainStateFile",vin["prevout"]["txhash"])
                        unSpendOut =  dto.utx.CUTx.deserializeFromJsonStr(unSpendOutStr)
                        
                        #del unSpendOut.unSpendOuts[vin["prevout"]["outindex"]]
                        for out in  unSpendOut.unSpendOuts:
                            if tx.txtype==1 :
                                if vin["prevout"]["outindex"] != out['outindex']  :
                                    updatedOuts.append(out)
                                else:
                                    revtx.consumeVoutTxhash.append(vin["prevout"]["txhash"])
                                    revtx.consumeVout.append(out)

                          
                            else:
                                updatedOuts.append(out)

                          

                        if len(updatedOuts)== 0 :
                            modules.db.CDb.deleteValue("chainStateFile",vin["prevout"]["txhash"])
                        else:
                            unSpendOut.unSpendOuts=updatedOuts
                            modules.db.CDb.setValue("chainStateFile",vin["prevout"]["txhash"],unSpendOut.serializeToJsonStr())
                    revblock.transactions.append(revtx.serializeToPyObject())
                newOutputs=None
                if tx.txtype==2:
                    newOutputs = dto.utx.CUTx(tx.selfhash,block.selfhash,block.timestamp,txtype=2)
                if tx.txtype==3:
                    newOutputs = dto.utx.CUTx(tx.selfhash,block.selfhash,block.timestamp,txtype=3)
                if tx.txtype==1:
                    newOutputs = dto.utx.CUTx(tx.selfhash,block.selfhash,block.timestamp)
                unSpendOuts = []

                for index,out in enumerate(tx.txouts):
                    outInfo = dto.utx.COutInfo(index,out).serializeToPyObject()
                    unSpendOuts.append(outInfo)
                newOutputs.unSpendOuts =unSpendOuts
                modules.db.CDb.setValue("chainStateFile",tx.selfhash,newOutputs.serializeToJsonStr())

           

            revstorefilename=f'{block.selfhash}-rev.dat'
            path=modules.appconfig.CAppconfig.configFromFile['chainFilePath']+block.selfhash[0:2]
            filename=f'{path}/{revstorefilename}'
            revblock.serializeToJsonfile(filename)

        else:
             #该区块还没有存储
             pass           
        
   

    def rollback(self,revblock,originblock):
        for revtx in revblock.transactions:
            revtx = dto.rollback.CRevTx.deserializeFromPyObject(revtx)
            modules.db.CDb.deleteValue("chainStateFile",revtx.txhash)

            for index,consumeVout in enumerate(revtx.consumeVout):
                unSpendOutStr = modules.db.CDb.getValueByKey("chainStateFile",revtx.consumeVoutTxhash[index])
                unSpendOut =  dto.utx.CUTx.deserializeFromJsonStr(unSpendOutStr)
                unSpendOut.unSpendOuts.insert(revtx.consumeVoutIndex[index], consumeVout)
                modules.db.CDb.setValue("chainStateFile",vin["prevout"]["txhash"],unSpendOut.serializeToJsonStr())
        # for tx in block.transactions:
        for index, tx in enumerate(originblock.transactions):
            #update txinfo in chainIndexdata
            modules.db.CDb.deleteValue("chainStateFile",tx['selfhash'])
        # modules.transaction.CTransaction.updatetotalstransactionnumber(originblock.txcounts,2)
           
    def saveIsolatedBlockToCachedPool(self,block):
        self.isolatedBockCachedPool.append(block)
    
    def clearIsolatedBlockToCachedPool(self):
        self.isolatedBockCachedPool=[]
    
    def addBlockToisolatedBlockPool(self,block):
        self.isolatedBlocks[block.selfhash] = block

    def getChainHeight(self):
        return self.last_block["height"]

    def findCommonBlock(self,foreignerAddr):
        blockoption = {
                'method': 'post',
                'api': '/getCommonblock',
                'data':{
                    "height":self.last_block['height'],
                    "blockshash":self.fivePreBlockhashDequeFromTheTipBlk
                    }
        }
        
        response= modules.net.pynet.CP2pnet.getFromPeer(foreignerAddr,blockoption)
        commonblockInfo=None
        if response.status_code == 200:
            values = response.json()
            commonblockInfo={
                'commonblockhash':values['commblkhash'],
                'commonheight': values['commheight']
            }
        return commonblockInfo
            
    def synchain(self,commonblockInfo,foreignerAddr):
        commonblockhash = commonblockInfo['commonblockhash']
        commonheight = commonblockInfo['commonheight']
        option = {
            'method': 'get',
            'api': '/getBlockshashToSync',
            'data':{
                "commonheight":commonheight,
                "maxNum":500
                }
        }
        response= modules.net.pynet.CP2pnet.getFromPeer(foreignerAddr,option)
        if response.status_code == 200:
            values = response.json()
            blckHashs = values['blockshashToSync']
            while len(blckHashs)>0:
                blkhash = blckHashs.pop(0)
                option = {
                    'method': 'GET',
                    'api': '/block',
                    'data':{
                        'blockhash':blkhash
                    }
                }
                node = modules.net.pynet.CP2pnet.getRandomNode()
                response=modules.net.pynet.CP2pnet.getFromPeer(node,option)
                if response!='' and response.status_code==200:
                    block = response.json()['block']
                    if block["height"] < self.last_block["height"]:
                        block = dto.block.CBlock.deserializeFromPyObject(block)
                        modules.block.CBlock.processBlock(block,6,node,False)
                    else:
                        flag,isAccepted=modules.block.CBlock.reciveBlock(block,node,False)
                        if isAccepted:
                            if flag==-1:
                                flag,isAccepted=modules.block.CBlock.tryRequestBlockFromNet(block['prevBlockHash'],node)
                            
                        else:
                            return False
            return True
        else:
            return False


    def syncChainWithOtherNode(self):
        kownodesNumber=modules.net.pynet.CP2pnet.getKnowNodesNumber()
        if kownodesNumber>0:
            # node = modules.net.pynet.CP2pnet.getRandomNode()
            host= modules.net.pynet.CP2pnet.address['host']
            port = modules.net.pynet.CP2pnet.address['port']
            data = {
                    'version': self.last_block['version'],
                    'chainHeight': self.last_block['height']
                    # 'addrFrom': f'{host}:{port}'
            }
            response = modules.net.pynet.CP2pnet.broadcast("chainInfo",data)
            if response!=None and response.status_code==200:
                foreignerChainHeight = response.json()['chainHeight']
                flag=0
                while self.last_block['height']<foreignerChainHeight:
                    commonblockInfo={}
                    foreignerAddr = response.json()['addrFrom']
                    if self.isFirstedLoad:
                        self.isFirstedLoad=False
                        commonblockInfo['commonblockhash']=self.last_block["selfhash"]
                        commonblockInfo['commonheight']= 0
                    else:
                        if flag==0:
                            flag=1
                            commonblockInfo=self.findCommonBlock(foreignerAddr)
                        else:
                            commonblockInfo['commonblockhash']=self.last_block["selfhash"]
                            commonblockInfo['commonheight']= self.last_block["height"]

                    isSyncRight=self.synchain(commonblockInfo,foreignerAddr)
                    if not isSyncRight:
                        break

                    # self.findCommonBlockAndSync(foreignerAddr)
                    # self.isFirstedLoad=False
                    data = {
                    'version': self.last_block['version'],
                    'chainHeight': self.last_block['height']
                    # 'addrFrom': f'{host}:{port}'
                    }
                    
                    response = modules.net.pynet.CP2pnet.broadcast("chainInfo",data)
                    if response!=None and response.status_code==200:
                        foreignerChainHeight = response.json()['chainHeight']
                    else:
                        break
    def syncChainWithTheNode(self,node):
            host= modules.net.pynet.CP2pnet.address['host']
            port = modules.net.pynet.CP2pnet.address['port']
            data = {
                    'version': self.last_block['version'],
                    'chainHeight': self.last_block['height']
            }
            response = modules.net.pynet.CP2pnet.broadcast("chainInfo",data,node=node)
            if response!=None and response.status_code==200:
                foreignerChainHeight = response.json()['chainHeight']
                flag=0
                while self.last_block['height']<foreignerChainHeight:
                    commonblockInfo={}
                    foreignerAddr = response.json()['addrFrom']
                    commonblockInfo=self.findCommonBlock(foreignerAddr)
                    # if flag==0:
                    #     flag=1
                    #     commonblockInfo=self.findCommonBlock(foreignerAddr)
                    # else:
                    #     commonblockInfo['commonblockhash']=self.last_block["selfhash"]
                    #     commonblockInfo['commonheight']= self.last_block["height"]
                    if commonblockInfo ==None:
                        break
                    isSyncRight=self.synchain(commonblockInfo,foreignerAddr)
                    if not isSyncRight:
                        break

                    data = {
                        'version': self.last_block['version'],
                        'chainHeight': self.last_block['height']
                    }
                    response = modules.net.pynet.CP2pnet.broadcast("chainInfo",data)
                    if response!=None and response.status_code==200:
                        foreignerChainHeight = response.json()['chainHeight']
                    else:
                        break
    def getBlockshashOnTheMainChain(self,commmonBlkHeight,MaxNum):
        blocksHashSet= []
        distance = self.last_block["height"] - commmonBlkHeight
        if distance <= MaxNum:
            blockshash = self.last_block["selfhash"]
            startHeight = self.last_block["height"]
        else:
            startHeight = commmonBlkHeight + MaxNum
            blockshash,flag= modules.block.CBlock.getBlockHashByHeightFromTheMainChainTip(startHeight)
        while len(blocksHashSet) <= MaxNum and startHeight > commmonBlkHeight :
                blocksHashSet.insert(0,blockshash) 
                storeInfo = modules.db.CDb.getValueByKey("chainIndexFile",blockshash)
                storeInfo = storeInfo.split(',')
                blockshash = storeInfo[1]
                startHeight = startHeight - 1
        
        return blocksHashSet
       
    def mine(self):
        # We run the proof of work algorithm to get the next proof...
        # if len(modules.transaction.CTransaction.current_transactions)>0:
            last_proof = self.last_block["proof"]
            proof =modules.consensus.CConsensus.proof_of_work(last_proof)

            # Forge the new Block by adding it to the chain
            height = self.last_block["height"]+1
            lastBlock_hash = self.last_block["selfhash"]
            while last_proof!= self.last_block["proof"] or  height!=self.last_block["height"]+1 or lastBlock_hash != self.last_block["selfhash"]:
                last_proof = self.last_block["proof"]
                proof =modules.consensus.CConsensus.proof_of_work(last_proof)
                height = self.last_block["height"]+1
                lastBlock_hash = self.last_block["selfhash"]

        
            privatekey="-----BEGIN RSA PRIVATE KEY-----\nMIICXwIBAAKBgQDtRfXdN1DtiD9AOu48rhuUEaQEJ2YS/7l5S97jCo9IO/A0nps9\n4nI3mANkUHTdvprkuqCnYJEkGU/Krr6tTYbKByAXRhTHWjVemwfOddSMpHnNFSSd\nWdWJygIZwV6NrRJVYUuNRcVi+w9XPE4tBgr+Oj7oeaUM36KWL0bIl2u0vQIDAQAB\nAoGBAOSc+NTpXF9RXGgdn7f1pXrYOGkMMQxzOpjFYn7tiLp3jeyVOUy6J4SrQfFg\nmAmjggiKTQqYP6BBhyDpl6zROuEIZ1o4g7kjxyb18kOl2zUygj9/R849njQsWE03\nNl/sV2biRiGw9ggMUAfEibVBgxYloYU0cnCZMdzSUbVurEadAkEA9maMuKoJ7J4P\n2JXdByVmfgwFKiVSK/3NR0nCTQZ6REEWR+lEzN5B6ufaykX+hX/eLbo1z4RoYv7/\nLyy4nv7OzwJBAPaEYWpWJngouCSclAtVX5tZWhvecdqjKrqXtRhr8digMbvg8X5y\nLcFaaxAdKrTfiMHBxTyfO8gSq3PxeR8jxrMCQQCdy5q/ABYO9EKNn5vG4cq7WhNM\npE31Yjo+Nxw5m7ZdU5ljQB4RXRy1xPm2pBCVigfNHP0tAkyfaVIe8fLhz6i9AkEA\nknQtR7Zs3mAani2jymPrC+j2nq316BWd8gLlJOAkazUotty5vAxrYH6uMoGReKmA\nntPWsOBM7N0inRwtgDGJ/wJBAIXokjlMSqAJ3cOdIqGslr8BWklz26bHuQuuWx6Z\ncmRyNaut2XlSoyNWdocc8F7/MAQ8GisZT697LxsFpgaGe1w=\n-----END RSA PRIVATE KEY-----"
            recipient="adasdfdasfdasfasfdasfadsfdasfdasdfasdfasf"
            newown='天娱传媒'
            content={
                'copyrightName':'《王牌对王牌第二季》任嘉伦一言不合就尬舞与李小璐演绎特殊身份',
                'workType':'短视频',
                'author':'天蚕土豆',
                'own':newown,
                'place':'中国江苏无锡',
                'finishDate':str(util.ctime.Ctime().getNowTimestamp()),
                'describe':'看好了好了好了厉害厉害了老厉害了',
                'effectiveDate':'2018-10-22',
                'periodOfvalidity':'50'
            }
            # modules.transaction.CTransaction.addCopyRightToChain(privatekey,recipient,content)
            block = modules.block.CBlock.generateBlock(proof,lastBlock_hash,height)
            modules.block.CBlock.processBlock(block,1) 
            block = block.serializeToPyObject()
            print(block)
           
    
    def indexBlockHashfromCurrentBLock(self,blockshash,height,num):
        PreBlockhashDeque=[]
        while len(PreBlockhashDeque) < num and height > 0 :
            #PreBlockhashDeque.append(block.prevBlockHash)
            PreBlockhashDeque.insert(0,blockshash) 
            storeInfo = modules.db.CDb.getValueByKey("chainIndexFile",blockshash).split(',')
            blockshash = storeInfo[1]
            height = height - 1
          
        return PreBlockhashDeque
    def handleIsolatedBockCachedPool(self,blockhash):
        isolatedBocks=self.isolatedBockCachedPool
        al=[]
        prebl=[]
        prebl.append(blockhash)
        while len(prebl)>0:
            blockhash=prebl.pop(0)
            for index in range(len(isolatedBocks)):
                if isolatedBocks[index]['prevBlockHash']== blockhash:
                    al.append(isolatedBocks[index])
            if len(al)>0:
                for index ,blk in enumerate(al):
                    # blk=isolatedBocks[index]
                    flag,isAccepted = modules.block.CBlock.reciveBlock(blk)
                    if isAccepted and flag!=-1:
                        index1=isolatedBocks.index(blk)
                        isolatedBocks.pop(index1)
                        prebl.append(blk['selfhash'])
    
    def getTheNewBlocksInfo(self,number=5):
        result=[]
        blkhash=self.last_block['selfhash']
        storeInfo=modules.db.CDb.getValueByKey("chainIndexFile",blkhash).split(',')
        height=int(storeInfo[0])
        t=0
        while t<number and height>0:
            a=int(storeInfo[2])
            if a>0:
                b={
                    "hash":blkhash,
                    "height":height,
                    "txcounts":a,
                    "time":storeInfo[3]
                }
                result.append(b)
                t=t+1
            blkhash=storeInfo[1]
            storeInfo=modules.db.CDb.getValueByKey("chainIndexFile",blkhash).split(',')
            height=height-1
        return result
    def getTheNewTransactionsInfo(self,number=5):
        
        result=[]
        blkhash=self.last_block['selfhash']
        storeInfo=modules.db.CDb.getValueByKey("chainIndexFile",blkhash).split(',')
        height=int(storeInfo[0])
        t=0
        while height>0 and t<5:
            a=int(storeInfo[2])
            if a>0:
                block=modules.block.CBlock.getBlockFromDiskByhash(blkhash)
                for tx in block.transactions:
                    sender=util.ccrypto.CCrypto.getAddressFromKeystr(tx['txins'][0]['scriptSig']['pubkey'])
                    recive=tx['txouts'][0]['scriptPubKey']['scriptPubkey']
                    copyrightID=tx['txouts'][0]['value']
                    copyrightContent=tx['txouts'][0]['content']
                    b={
                        "blockhash":blkhash,
                        "sender":sender,
                        "recive":recive,
                        "copyrightID":copyrightID,
                        "copyrightContent":copyrightContent,
                        "time":storeInfo[3]
                    }
                    result.append(b)
                    t=t+1
            blkhash=storeInfo[1]
            storeInfo=modules.db.CDb.getValueByKey("chainIndexFile",blkhash).split(',')
            height=height-1
        return result
                        
    def __attachApi(self):

      
        
        @modules.net.pynet.CP2pnet.severapp.route('/blockquery/<blockhash>',methods=['GET'])
        def blockquery(blockhash):
            
            if blockhash == "#" or blockhash == "":
               
                return render_template("blockquery.html",block = self.last_block)
            else:

                storefilename=f'{blockhash}.dat'
                path=modules.appconfig.CAppconfig.configFromFile['chainFilePath']+blockhash[0:2]
                filename=f'{path}/{storefilename}'
                block = dto.block.CBlock.deserializeFromJsonfile(filename)
                return render_template("blockquery.html",block = block.serializeToPyObject())
        @modules.net.pynet.CP2pnet.severapp.route('/getblockInfo/<blockhash>',methods=['GET'])
        def getblockInfo(blockhash):        
                isStored, storeInfo =  modules.block.CBlock.ifBlockIsStoredLocal(blockhash)
                if isStored:
                    storeInfo=storeInfo.split(",")
                    storefilename=f'{blockhash}.dat'
                    path=modules.appconfig.CAppconfig.configFromFile['chainFilePath']+blockhash[0:2]
                    filename=f'{path}/{storefilename}'
                    block = dto.block.CBlock.deserializeFromJsonfile(filename)
                   
                    transactions=[]
                    for tx in block.transactions:
                        sender=util.ccrypto.CCrypto.getAddressFromKeystr(tx['txins'][0]['scriptSig']['pubkey'])
                        recive=tx['txouts'][0]['scriptPubKey']['scriptPubkey']
                        copyrightID=tx['txouts'][0]['value']
                        copyrightContent=tx['txouts'][0]['content']
                        b={
                            "blockhash":blockhash,
                            "sender":sender,
                            "recive":recive,
                            "copyrightID":copyrightID,
                            "copyrightContent":copyrightContent,
                            "time":storeInfo[3]
                        }
                        transactions.append(b)
                    data={
                       "height":int(storeInfo[0]),
                       "parenthash":storeInfo[1],
                       "blockhash":blockhash,
                       "transactionNumber":int(storeInfo[0]),
                       "time":storeInfo[3],
                       "transactions":transactions

                    }
                    return jsonify(data), 200
                else:
                    data={
                        'status':501,
                        "message":"this block is not exit"
                    }
                    return jsonify(block), 200
          
               
        
        @modules.net.pynet.CP2pnet.severapp.route('/copyrightListquery/<address>',methods=['GET'])
        def copyrightListquery(address):
            copyrightList=modules.transaction.CTransaction.getcopyrightListByaddress(address)
            response = {
                'status':500,
                'copyrightList':copyrightList
            }
            return jsonify(copyrightList), 200 
        @modules.net.pynet.CP2pnet.severapp.route('/getcopyrightContent/<copyrightID>',methods=['GET'])
        def handleGetcopyrightContent(copyrightID):
            copyrightContent=modules.transaction.CTransaction.getcopyrightContentBycopyrightID(copyrightID)
            if copyrightContent!="":
                response = {
                    'status':200,
                    'copyrightContent':copyrightContent
                }
                return jsonify(response), 200   
            else:
                confirnumber,copyrightContent=self.findcopyrightcotent(copyrightID)
                if confirnumber>=0 and copyrightContent!="":
                    response = {
                        'status':200,
                        'copyrightContent':copyrightContent,
                        'nowconfirm':confirnumber,
                        'tip':'this copyright cannot transantion now'
                    }
                    return jsonify(response), 200 
                else:
                    response = {
                        'status':201,
                        'message':"can not find info about the ID"
                    }
                    return jsonify(response), 200  
        @modules.net.pynet.CP2pnet.severapp.route('/getsystemInfo',methods=['GET'])
        def handleGetsystemInfo():
            activeNodeNumber=1
            totalnode=2
            totaltransanctions=modules.transaction.CTransaction.gettotalstransactionnumber()
            response = {
                'activenode':activeNodeNumber,
                'blockheight':self.last_block['height'],
                'totalnode':totalnode,
                'totaltransanctions':totaltransanctions
            }
            return jsonify(response), 200  
        @modules.net.pynet.CP2pnet.severapp.route('/gettheNewBlocksinfo',methods=['GET'])
        def handleGettheNewBlocksinfo():
            result=self.getTheNewBlocksInfo()
            return jsonify(result), 200  
        
        @modules.net.pynet.CP2pnet.severapp.route('/gettheNewTransactioninfo',methods=['GET'])
        def handlegettheNewTransactioninfo():
            result=self.getTheNewTransactionsInfo()
            return jsonify(result), 200  


    

        
        #接受从网络中传来的block
        @modules.net.pynet.CP2pnet.severapp.route('/block',methods=['POST'])
        def recieveBlockFromNet():
            values = request.get_json()
            if values!=None:
                remote_addr = values['addrFrom']
                block=values['data']
                preblockhash=block['prevBlockHash']
                blockhash=block['selfhash']
                blockheight=block['height']
                modules.log.Clog.logger.info("远端节点ip。。。。。。。。。。。。。。"+remote_addr)
                flag,isAccepted= modules.block.CBlock.reciveBlock(block,remote_addr)
                if isAccepted:
                    if flag!=-1:
                        self.handleIsolatedBockCachedPool(blockhash)
                    if flag==-1:
                        if blockheight>self.last_block["height"]:
                            self.syncChainWithTheNode(remote_addr)
                        else:
                            if  len(self.isolatedBockCachedPool) ==5 :
                                self.isolatedBockCachedPool.pop(0)
                            self.saveIsolatedBlockToCachedPool(block)
                            modules.block.CBlock.tryRequestBlockFromNet(preblockhash,remote_addr)
                    response = {'message': f'Block is recived '}
                    return jsonify(response), 201
                else:
                    return 'Block is rejected', 401  
            else:
                return 'request data is not josn format', 401 

        @modules.net.pynet.CP2pnet.severapp.route('/getTheTopblock',methods=['GET'])
        def handlegetTheTopblock():
            data={
                    "block":self.last_block
            }
            return jsonify(data),200

        #响应网络请求block
        @modules.net.pynet.CP2pnet.severapp.route('/block',methods=['GET'])
        def handleBlockrequire():
            values = request.get_json()
            if values!=None:
                isStored, blkStoreInfo =modules.block.CBlock.ifBlockIsStoredLocal(values['blockhash'])
                if isStored:
                    blck = modules.block.CBlock.getBlockFromDiskByhash(values['blockhash'])
                    data={
                        "block":blck.serializeToPyObject()
                    }
                    return jsonify(data),200
                else:
                    data={
                        "message":"request block is not stored"
                    }
                    return jsonify(data),201
            else:
                return 'request data is not josn format', 401 

              
        @modules.net.pynet.CP2pnet.severapp.route('/chainInfo',methods=['POST'])
        def handleChainInfo():
            values = request.get_json()
            if values!=None:

                required = ['version', 'chainHeight']
                foreignerAddr = values['addrFrom']
                data=values['data']
                if not all(k in data for k in required):
                    return 'Missing values', 400
                foreignerChainHeight =data['chainHeight']
            
                """
                if not foreignerAddr in modules.net.pynet.CP2pnet.knowNodes():
                    modules.net.pynet.CP2pnet.register_node(foreignerAddr)
                """
                # Check if the length is longer 
                max_length = self.last_block["height"]
                if foreignerChainHeight > max_length:
                    self.findCommonBlockAndSync(foreignerAddr)
                    return "chain is lower",201
                else:
                    host= modules.net.pynet.CP2pnet.address['host']
                    port = modules.net.pynet.CP2pnet.address['port']
                    data = {
                        'version': self.last_block['version'],
                        'chainHeight': self.last_block['height'],
                        'addrFrom': f'{host}:{port}'
                    }
                    if max_length==foreignerChainHeight:
                        modules.net.pynet.CP2pnet.register_node(foreignerAddr)

                    return jsonify(data), 200 
            else:
                return 'request data is not josn format', 401 
        @modules.net.pynet.CP2pnet.severapp.route('/netNodesInfo',methods=['POST'])
        def handleNetNodesInfo():
            values = request.get_json()
            if values!=None:
                # required = ['addrFrom', 'data']
                foreignerAddr = values['addrFrom']
                fromKowNodes=values['data']
            
                data=""
                state=201
                host= modules.net.pynet.CP2pnet.address['host']
                port = modules.net.pynet.CP2pnet.address['port']
                result=modules.db.Sqlite3Db.node_findByState(excludeNode=foreignerAddr)
                if result!=None and  len(result)>0:
                    nodes=[]
                    for row in result:
                            a={
                                'hostAndport':row[0],
                                'state':0
                            }
                            if a not in fromKowNodes :
                                nodes.append(a)
                    
                    data = {
                            'addrFrom': f'{host}:{port}',
                            'data':nodes
                    }
                    state=200 
                else:
                    data={
                        'addrFrom': f'{host}:{port}',
                        'message':"has no know node"
                    }
                    sate=201
                a={
                        'hostAndport':f'{host}:{port}',
                        'state':0
                    }
                if a in fromKowNodes:
                    del fromKowNodes[fromKowNodes.index(a)]
                modules.db.Sqlite3Db.node_addNodes(fromKowNodes)
                return jsonify(data), state
            else:
                return 'request data is not josn format', 401 
            
        @modules.net.pynet.CP2pnet.severapp.route('/getCommonblock',methods=['POST'])
        def handleGetCommonBlock():
            commblkhash=""
            commheight=-1
            requestdatas = request.get_json()
            height = requestdatas['height']
            blockshashs= requestdatas['blockshash']
            if len(blockshashs)>0 :
                while len(blockshashs)>0 and height >1:
                    blkhash = blockshashs.pop()
                    isStored,storeInfo = modules.block.CBlock.ifBlockIsStoredLocal(blkhash)
                    if isStored :
                        comblkhash,comheight=modules.block.CBlock.findCommonBlockOnMainChain(blkhash,height)
                        if comblkhash !="":
                            commblkhash = comblkhash
                            commheight = comheight
                            break
                    height = height -1
                if commblkhash !="":
                    data = {
                        "commblkhash":commblkhash,
                        "commheight":commheight 
                    }
                    return jsonify(data), 200 
                else:
                    return "Not Find common Block",201
            else:
                genesisBlockHash = self.getGenesisBlockHash()
                data = {
                        "commblkhash":genesisBlockHash,
                        "commheight":0 
                }
                return jsonify(data), 200 

        @modules.net.pynet.CP2pnet.severapp.route('/getBlockshashToSync',methods=['GET'])
        def handleGetBlockshash():
            requestdatas = request.get_json()
            blckHashs = self.getBlockshashOnTheMainChain(requestdatas['commonheight'],requestdatas['maxNum'])
            host= modules.net.pynet.CP2pnet.address['host']
            port = modules.net.pynet.CP2pnet.address['port']
            data = {
                    'blockshashToSync': blckHashs,
                    'addrFrom': f'{host}:{port}'
            }
            return jsonify(data), 200 
        @modules.net.pynet.CP2pnet.severapp.route('/isOnline',methods=['GET'])
        def handleQueryisOnline():
            host= modules.net.pynet.CP2pnet.address['host']
            port = modules.net.pynet.CP2pnet.address['port']
            data = {
                    'message': 'I am online',
                    'addrFrom': f'{host}:{port}'
            }
            return jsonify(data), 200 

        
           


    




        
    
    